package model

// IEventDrivenModel defines an event driven model for code arrangement
type IEventDrivenModel interface {
	Hook(e string, handleFunc TEventHandleFunc)
	Fire(e string, args ...interface{})
	FireAsync(e string, args ...interface{})
}

type TEventHandleFunc func(e string, args ...interface{})

type TEventDrivenModel struct {
	items map[string][]TEventHandleFunc
}

func (me *TEventDrivenModel) Hook(e string, handler TEventHandleFunc) {
	if me.items == nil {
		me.items = make(map[string][]TEventHandleFunc)
	}

	arr, ok := me.items[e]
	if ok {
		me.items[e] = append(arr, handler)
	} else {
		me.items[e] = []TEventHandleFunc{handler}
	}
}

func (me *TEventDrivenModel) Fire(e string, args ...interface{}) {
	if handlers, ok := me.items[e]; ok {
		for _, it := range handlers {
			it(e, args...)
		}
	}
}

func (me *TEventDrivenModel) FireAsync(e string, args ...interface{}) {
	go me.Fire(e, args...)
}
